﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace D
{

    //    一、什么是装饰器模式？
    //装饰器模式是一种结构型设计模式，它的核心思想是：

    //在不修改原有对象的前提下，动态地添加新的功能，通过“包装”方式实现功能扩展。
    //你可以把它想象成：
    //给一个对象穿上“功能外衣”，每加一层装饰，就多一个行为。
    //就像给咖啡加奶、加糖、加巧克力 —— 每一层装饰都叠加新的口味（功能）。


    //    二、适用场景
    //装饰器模式适用于以下情况：

    //需要在不改变原始类代码的情况下扩展对象功能。
    //希望通过组合方式替代继承实现功能扩展。
    //系统中有大量的功能组合需求（例如I/O 流、UI控件样式等）。
    //不想造成子类爆炸式增长（为了避免为每种功能组合都写一个子类）。


    //    三、结构组成（UML）
    //          角色                              说明
    //Component（抽象组件）	            定义对象接口，可以是接口或抽象类
    //ConcreteComponent（具体组件）	    被装饰的原始对象
    //Decorator（装饰器基类）	            持有一个 Component 实例，并实现相同接口
    //ConcreteDecorator（具体装饰器）	    添加额外功能的装饰类

    //    五、优缺点分析
    //✅ 优点
    //不修改原始类的前提下扩展功能（符合开闭原则）。
    //可叠加的功能组合，灵活多变。
    //避免类爆炸（相较于继承方案）。

    //❌ 缺点
    //类的数量增多（每种功能都需要一个装饰类）。
    //多层嵌套调用时调试不太直观。


    //    六、与代理/继承的区别
    //模式            意图               关键点
    //装饰器       增强功能     包装并增强，调用原始对象
    //代理模式     控制访问     包装对象，控制访问权限、延迟加载
    //继承         静态扩展     编译时确定，容易出现类爆炸
    //装饰器       动态组合     运行时叠加多个功能，灵活

    //    七、实际开发中应用场景
    //  应用领域                        装饰用途
    //Java/C# I/O 流	        FileInputStream → BufferedInputStream → DataInputStream
    //WPF/WinForms UI控件    通过附加样式、行为进行装饰
    //日志系统               为服务方法添加日志功能
    //权限系统               给服务接口添加认证逻辑
    //游戏技能系统           英雄技能套装叠加（如加速+隐身+加血）


    //    八、总结一句话
    //当你需要在运行时为对象“添加功能”，并且不希望通过继承来实现时，使用装饰器模式就是最优解。

    /// <summary>
    /// 抽象组件
    /// </summary>
    public abstract class AbstractBeverage
    {
        public abstract string GetDescription();
        public abstract double Cost();
    }

    /// <summary>
    /// 具体组件
    /// </summary>
    public class Espresso : AbstractBeverage
    {
        public override string GetDescription() => "浓缩咖啡";

        public override double Cost() => 10.0;
    }

    /// <summary>
    /// 装饰器基类
    /// </summary>
    public abstract class AddonDecorator : AbstractBeverage
    {
        protected AbstractBeverage beverage;   //饮料

        public AddonDecorator(AbstractBeverage beverage)
        {
            this.beverage = beverage;
        }
    }

    /// <summary>
    /// 具体装饰器-1 Milk
    /// </summary>
    public class Milk : AddonDecorator
    {
        public Milk(AbstractBeverage beverage) : base(beverage) { }

        public override string GetDescription() => beverage.GetDescription() + " + 牛奶";

        public override double Cost() => beverage.Cost() + 2.0;
    }

    /// <summary>
    /// 具体装饰器-2 Mocha
    /// </summary>
    public class Mocha : AddonDecorator
    {
        public Mocha(AbstractBeverage beverage) : base(beverage) { }

        public override string GetDescription() => beverage.GetDescription() + " + 摩卡";

        public override double Cost() => beverage.Cost() + 3.0;
    }

    /// <summary>
    /// 具体装饰器-3 Chocolate
    /// </summary>
    public class Chocolate : AddonDecorator
    {
        public Chocolate(AbstractBeverage beverage) : base(beverage) { }

        public override string GetDescription() => beverage.GetDescription() + " + 巧克力";

        public override double Cost() => beverage.Cost() + 5.3;
    }



    class Program
    {
        static void Main(string[] args)
        {
            //func1();

            func2();

            Console.ReadKey();
        }

        static void func1()
        {
            IDecorator decorator = new Decorator();
            decorator.Component = new Component();
            decorator.Operation();
            decorator.NewBehavior();
        }

        static void func2()
        {
            AbstractBeverage coffee = new Espresso();       // 原始浓缩咖啡
            coffee = new Mocha(coffee);                     // 再加摩卡
            coffee = new Milk(coffee);                      // 加牛奶
            coffee = new Chocolate(coffee);                 // 再加巧克力

            Console.WriteLine(coffee.GetDescription());     // 输出: 浓缩咖啡+摩卡+牛奶+巧克力
            Console.WriteLine("总价: " + coffee.Cost());    // 输出:  总价: 15
        }


    }
}
